package com.lifeng.fastssmr.base.impl;

import java.io.File;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;

import com.lifeng.fastssmr.base.BaseDao;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBObject;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;
import com.mongodb.gridfs.GridFSInputFile;

public abstract class BaseDaoImpl<T> implements BaseDao<T> {
    private static Logger logger = Logger.getLogger(BaseDaoImpl.class);
	@Autowired
    private MongoTemplate mongoTemplate;
	@Autowired
	private GridFsTemplate gridFsTemplate;
	
	private Class<T> clazz = null;
    //通过反射技术得到T的真实类型
    public BaseDaoImpl(){
    	//获得当前new的对象的父类的类型
    	ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
    	//获得第一个参数类型的真实类型
    	this.clazz = (Class<T>)pt.getActualTypeArguments()[0];
    }
    
	/* (non-Javadoc)
	 * @see com.lifeng.fastssmr.base.impl.BaseDao1#delete(T)
	 */
	@Override
	public void delete(T object) {
		logger.info("删除对象:"+object);
		if(object!= null){
			mongoTemplate.remove(object);
		}
	}
	public void delete(Serializable id){
		mongoTemplate.remove(getById(id));
	}
	/* (non-Javadoc)
	 * @see com.lifeng.fastssmr.base.impl.BaseDao1#findAll()
	 */
	@Override
	public List<T> findAll() {
		return mongoTemplate.findAll(clazz);
	}

	/* (non-Javadoc)
	 * @see com.lifeng.fastssmr.base.impl.BaseDao1#getById(java.io.Serializable)
	 */
	@Override
	public T getById(Serializable id) {
		if(id==null){
			return null;
		}else{
			return (T)mongoTemplate.findById(id,clazz);
		}
		
	}

	/* (non-Javadoc)
	 * @see com.lifeng.fastssmr.base.impl.BaseDao1#getByIds(java.io.Serializable[])
	 */
	@Override
	public List<T> getByIds(Serializable[] ids) {
		if(ids.length==0||ids==null){
			return null;
		}
		List<T> list = new ArrayList<T>();
		for (int i = 0; i < ids.length; i++) {
			list.add(getById(ids[i]));
		}
		return list;
	}
	
	/* (non-Javadoc)
	 * @see com.lifeng.fastssmr.base.impl.BaseDao1#deleteByIds(java.io.Serializable[])
	 */
	@Override
	public void deleteByIds(Serializable[] ids){
		for(int i=0;i<ids.length;i++){
			delete(ids[i]);
		}
		
	}
	
	/* (non-Javadoc)
	 * @see com.lifeng.fastssmr.base.impl.BaseDao1#save(T)
	 */
	@Override
	public void save(T entity) {
		mongoTemplate.save(entity);
	}

	/* (non-Javadoc)
	 * @see com.lifeng.fastssmr.base.impl.BaseDao1#update(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update)
	 */
	@Override
	public void update(Query query,Update update) {
		mongoTemplate.updateMulti(query, update, clazz);
	}
	
	/* (non-Javadoc)
	 * @see com.lifeng.fastssmr.base.impl.BaseDao1#getPageData(int, int)
	 */
	@Override
	public List<T> getPageData(int pageNum,int pageSize,Map<String,Object> param,Map<String,Object> orderPara){
		Query querySelect = new Query();//查询条件
        if(!param.isEmpty() && param != null){
        	for(Entry<String,Object> es :param.entrySet()){
        		querySelect.addCriteria(Criteria.where(es.getKey()).is(es.getValue()));
        	}
        	
        }
        if(!orderPara.isEmpty() && orderPara != null){
        	for(Entry<String,Object> ord :orderPara.entrySet()){
        		querySelect.with(new Sort(new Sort.Order(ord.getValue().equals("asc") ? Sort.Direction.ASC : Sort.Direction.DESC, ord.getKey())));  
        	}
        }
        querySelect.skip(pageNum);  
    	querySelect.limit(pageSize); 
		return mongoTemplate.find(querySelect,clazz);
	}
	
	/**
	 * 保存文件，并返回文件id
	 * @param in
	 * @param filename
	 * @param contentType
	 * @param metadata
	 * @return
	 * @throws Exception
	 */
	public String saveFile(InputStream in,String filename,String contentType,DBObject metadata) throws Exception{
		try {
			DB db = mongoTemplate.getDb();
			return gridFsTemplate.store(in, filename, contentType, metadata).getId().toString();
		} catch (Exception e) {
			e.printStackTrace();
			throw new Exception("保存文件异常",e);
		}
		
	}
	/**
	 * 通过fileId 获取文件,返回唯一
	 * @param fileId
	 * @return
	 */
	public GridFSDBFile findOneFile(String fileId){
		GridFSDBFile gridFSDBFile = gridFsTemplate.findOne(new Query(Criteria.where("_id").is(fileId)));
		return gridFSDBFile;
	}
	/**
	 * 根据条件查询文件
	 * @param query
	 * @return
	 */
	public List<GridFSDBFile> findAllFile(Query query){
		List<GridFSDBFile> gridFSDBFile = gridFsTemplate.find(query);
		return gridFSDBFile;
	}
	
	/**
	 * 通过文件id删除
	 * @param fileId
	 */
	public void deleteFileByFileId(String fileId){
		gridFsTemplate.delete(new Query(Criteria.where("_id").is(fileId)));
	}
	/**
	 * 通过条件删除
	 * @param query
	 */
	public void deleteByQuery(Query query){
		gridFsTemplate.delete(query);
	}
	
	/**
	 * 获取总记录数
	 */
	public  int getCount(Map<String,Object> param){
		Query querySelect = new Query();//查询条件
        if(!param.isEmpty() && param != null){
        	for(Entry<String,Object> es :param.entrySet()){
        		querySelect.addCriteria(Criteria.where(es.getKey()).is(es.getValue()));
        	}
        }
        Long count = mongoTemplate.count(querySelect, clazz);
		return count.intValue();
	}
}
